//import ... from ... 语句，从axios这个js框架中导入axios组件
import axios from 'axios';
import {TOKEN} from "../util/constant.js";
import {confirmMessage} from "../util/message.js";

// 设置axios默认请求基础URL
// 所有通过axios发送的请求都会自动拼接此基础URL
// 例如请求'/api/login'实际会发送到'http://localhost:8088/api/login'
axios.defaults.baseURL = 'http://localhost:8088';

// 请求拦截器 - 在发送请求前执行
axios.interceptors.request.use(
    // 请求成功拦截处理函数
    config => {
        // 从sessionStorage获取登录令牌
        let token = window.sessionStorage.getItem(TOKEN);
        // 将令牌添加到请求头Authorization字段
        config.headers.Authorization = token;
        // 返回修改后的配置对象
        return config;
    },
    // 请求错误拦截处理函数
    error => {
        // 拒绝Promise并返回错误信息
        return Promise.reject(error);
    }
)

// 响应拦截器 - 在接收响应后执行
axios.interceptors.response.use(
    // 响应成功拦截处理函数
    resp => {
        /**
         * 令牌过期处理逻辑
         * 后端约定：当响应状态码 > 900 时，表示令牌已过期或无效
         * 处理流程：显示确认对话框 -> 用户确认则清除令牌并跳转登录页 -> 用户取消则不执行操作
         */
        // 检查响应状态码，大于900视为令牌过期
        if (resp.data.code > 900) {
            // 输出令牌过期提示（结合后端返回消息）
            confirmMessage(resp.data.msg + ',是否重新登录?', 'warning').then(() => {
                // 重新登录流程：清除本地存储的令牌并强制跳转至登录页面
                window.sessionStorage.removeItem(TOKEN);
                window.location.href = '/';
            }).catch(() => {
                // 用户取消重新登录：不执行任何操作（此时用户可能无法继续使用需要权限的功能）
            })
        }
        // 返回响应对象
        return resp;
    },
    // 响应错误拦截处理函数
    error => {
        // 拒绝Promise并返回错误信息
        return Promise.reject(error);
    }
)

/**
 * 封装post请求函数
 * 当我们export导出该函数，那么其他页面/组件就可以通过import导入该函数，来使用该函数
 * @param url
 * @param param
 * @returns {Promise<AxiosResponse<any>> | *}
 */
export const doPost = (url, param) => {
    //通过配置方式，请求后端
    return axios({
        method: 'post', //请求方式是post
        url: url, //post请求的地址
        responseType: 'json', //post请求后端返回的数据类型是json
        data: param //post请求体（body）提交的参数，`data` 是作为请求体被发送的数据，`params`是与请求一起发送的URL参数
    })
}

/**
 * 封装get请求函数
 * @param url
 * @param param
 * @returns {Promise<AxiosResponse<any>> | *}
 */
export const doGet = (url, param) => {
    //通过配置方式，请求后端
    return axios({
        method: 'get', //请求方式是get
        url: url, //get请求的地址
        responseType: 'json', //get请求后端返回的数据类型是json
        params: param //get请求体（body）提交的参数，`data` 是作为请求体被发送的数据，`params`是与请求一起发送的URL参数
    })
}

/**
 * 封装put请求函数
 * @param url
 * @param param
 * @returns {Promise<AxiosResponse<any>> | *}
 */
export const doPut = (url, param) => {
    //通过配置方式，请求后端
    return axios({
        method: 'put', //请求方式是put
        url: url, //put请求的地址
        responseType: 'json', //put请求后端返回的数据类型是json
        data: param //put请求体（body）提交的参数，`data` 是作为请求体被发送的数据，`params`是与请求一起发送的URL参数
    })
}

/**
 * 封装delete请求函数
 * @param url
 * @param param
 * @returns {Promise<AxiosResponse<any>> | *}
 */
export const doDelete = (url, param) => {
    //通过配置方式，请求后端
    return axios({
        method: 'delete', //请求方式是delete
        url: url, //delete请求的地址
        responseType: 'json', //delete请求后端返回的数据类型是json
        params: param //delete请求体（body）提交的参数，`data` 是作为请求体被发送的数据，`params`是与请求一起发送的URL参数
    })
}

/**
 * 封装文件下载请求函数
 * 用于从后端下载文件，将响应类型设置为blob以处理二进制数据
 * @param url - 请求地址
 * @param param - 请求参数，作为URL参数发送
 * @returns {Promise<AxiosResponse<any>>} - 返回axios请求Promise
 */
export const doDownload = (url, param) => {
    //通过配置方式，请求后端
    return axios({
        method: 'get', //请求方式为GET
        url: url, //请求的地址
        responseType: 'blob', //设置响应类型为blob，以便处理二进制数据（如文件下载）
        params: param // `params`是与请求一起发送的URL参数
    })
}
